Skip to content

Conversation

@adamperlin
Copy link
Contributor

@adamperlin adamperlin commented Jan 5, 2026

This PR addresses some review feedback in #122301 and fills in more codegen for casts on Wasm.
Notably:

  • Casts from small int types (byte, short) are now supported with proper sign extension
    • Some generic casting code, in particular GenIntCastDesc was moved out of ifdefs and adapted for Wasm to support this. We don't yet support pushing down casts into loads (i.e., the LOAD_* integer cast types).
  • float->int casts are implemented using the saturating non-trapping conversion instructions
    • This required changing the type of our Wasm opcodes to be 2 bytes instead of 1

@github-actions github-actions bot added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Jan 5, 2026
@am11 am11 added the arch-wasm WebAssembly architecture label Jan 5, 2026
@dotnet-policy-service
Copy link
Contributor

Tagging subscribers to 'arch-wasm': @lewing, @pavelsavara
See info in area-owners.md if you want to be subscribed.

@adamperlin adamperlin force-pushed the adamperlin/ryujit-wasm-cast branch from 521f043 to c88d66b Compare January 14, 2026 17:35
@adamperlin adamperlin marked this pull request as ready for review January 14, 2026 18:36
Copilot AI review requested due to automatic review settings January 14, 2026 18:36
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR extends WebAssembly JIT cast operation support by implementing saturating float-to-int conversions and small integer casts with proper sign extension.

Changes:

  • Added support for casts from small int types (byte, short) with proper sign/zero extension
  • Implemented float-to-int casts using saturating non-trapping conversion instructions (requiring 2-byte opcodes)
  • Extended opcode type from uint8_t to uint16_t to support 2-byte instruction encoding
  • Moved GenIntCastDesc constructor out of TARGET_64BIT ifdefs to support WASM

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
src/coreclr/jit/morph.cpp Skip helper call morphing for float-to-long casts on WASM (direct saturating instruction support)
src/coreclr/jit/instrswasm.h Add load-with-extension, conversion, and saturating truncation instructions; align formatting
src/coreclr/jit/gentree.cpp Update cost estimation for WASM cast operations
src/coreclr/jit/emitwasm.cpp Change opcode type to uint16_t and add 2-byte opcode emission logic
src/coreclr/jit/cpp.hint Add multiple assert macro definitions for IntelliSense
src/coreclr/jit/codegenwasm.cpp Implement genIntToIntCast, genFloatToIntCast, genFloatToFloatCast; add PackTypes helper; handle TYP_INT from TYP_LONG in genCodeForLclVar
src/coreclr/jit/codegenlinear.cpp Move genCodeForCast and GenIntCastDesc to support WASM; add WASM to TARGET_64BIT conditionals
src/coreclr/jit/codegeninterface.h Change instInfo type to uint16_t for WASM
src/coreclr/jit/codegen.h Add WASM to TARGET_64BIT conditionals in GenIntCastDesc

@adamperlin adamperlin force-pushed the adamperlin/ryujit-wasm-cast branch from d86e911 to cc76584 Compare January 15, 2026 19:52
@adamperlin
Copy link
Contributor Author

@dotnet/jit-contrib Initial feedback should be implemented now so this is ready for another review pass!

//
static constexpr uint32_t PackOperAndType(genTreeOps oper, var_types toType, var_types fromType)
{
if (fromType == TYP_BYREF)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should also convert TYP_REF

//
static constexpr uint32_t PackTypes(var_types toType, var_types fromType)
{
if (toType == TYP_BYREF)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here

m_extendSrcSize = srcSize;
}

#ifndef TARGET_WASM
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you need this ifdef? I think things will work correctly without it (since we don't actually do any containment for casts yet).

Comment on lines +554 to +555
GetEmitter()->emitIns(INS_i32_and);
ins = (toType == TYP_LONG) ? INS_i64_extend_u_i32 : INS_none;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
GetEmitter()->emitIns(INS_i32_and);
ins = (toType == TYP_LONG) ? INS_i64_extend_u_i32 : INS_none;
ins = INS_i32_and;

This type of cast always produces a TYP_INT value.

// Return Value:
// oper and the types packed into an integer that can be used as a switch value/case
//
static constexpr uint32_t PackOperAndType(genTreeOps oper, var_types toType, var_types fromType)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This variant looks unused.

instruction ins = INS_none;
assert(fromType == TYP_INT || fromType == TYP_LONG);

genConsumeOperands(cast);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need an NYI for checked (gtOverflow) casts. Also applies to genFloatToIntCast.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

arch-wasm WebAssembly architecture area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants